package cn.bitleo.app

import android.Manifest
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.os.*
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.core.content.ContextCompat
import cn.bitleo.app.ui.theme.ExptTheme
import org.json.JSONObject
import java.io.*
import java.nio.charset.StandardCharsets
import ai.onnxruntime.*
import cn.bitleo.app.src.main.java.Injury.Injury3DModule

class MainActivity : ComponentActivity() {

    private val handler = Handler(Looper.getMainLooper())
    private val intervalMs = 3000L

    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted ->
        if (isGranted) {
            clearResultsDir()
            startScheduledInference()
        } else {
            Toast.makeText(this, "需要存储权限才能读取测试文件", Toast.LENGTH_LONG).show()
        }
    }

    @SuppressLint("SdCardPath")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            ExptTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Greeting("伤害评估系统", modifier = Modifier.padding(innerPadding))
                }
            }
        }

        // Android 10 权限处理
        if (ContextCompat.checkSelfPermission(
                this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            clearResultsDir()
            startScheduledInference()
        } else {
            requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
        }
    }

    // 清理 /Download/ALResults
    private fun clearResultsDir() {
        val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
        val resultDir = File(downloadsDir, "ALResults").apply { if (!exists()) mkdirs() }
        resultDir.listFiles()?.forEach { it.delete() }
    }

    private fun startScheduledInference() {
        handler.post(object : Runnable {
            override fun run() {
                startInferenceProcess()
                handler.postDelayed(this, intervalMs)
            }
        })
    }

    private fun startInferenceProcess() {
        Thread {
            try {
                val env = OrtEnvironment.getEnvironment()
                val modelFile = File(getExternalFilesDir(null), "models/injury_level_model_reshaped.onnx")
                if (!modelFile.exists()) return@Thread
                val session = env.createSession(modelFile.absolutePath, OrtSession.SessionOptions())

                val myModule = Injury3DModule(env, session)

                val testFile = File(Environment.getExternalStorageDirectory(), "AINeed/AINeed.csv")
                if (!testFile.exists()) return@Thread
                val lastLine = getLastLineUtf8(testFile)
                if (lastLine.isBlank()) return@Thread
                val values = parseCsvLine(lastLine)
                if (values.size < 6) return@Thread

                val patientId = values[0].trim()
                val floatArray = FloatArray(5) { j -> values[j + 1].toFloat() }
                val ultrasoundVal=values[6].trim()


                val result2D: Array<FloatArray> = myModule.inferFrom1D(floatArray)
                val modelOutput: FloatArray = result2D[0]

                val finalSeverity = calculateFinalSeverity(modelOutput, faceVal = 5.0f, ultrasoundVal = ultrasoundVal)
                val injuryDesc = mapToSeverityDesc(finalSeverity)

                saveResults(patientId, injuryDesc)
                val safePatientId = patientId.replace(Regex("[^a-zA-Z0-9_-]"), "_")

                Log.i("Inference", "Patient $safePatientId final severity: $injuryDesc")

            } catch (e: Exception) {
                Log.e("Inference", "错误: ${e.message}")
            }
        }.start()
    }

    // UTF-8 读取 CSV 最后一行，保证中文不乱码
    private fun getLastLineUtf8(file: File): String {
        BufferedReader(InputStreamReader(FileInputStream(file), StandardCharsets.UTF_8)).use { reader ->
            var line: String? = null
            var lastLine: String? = null
            while (true) {
                line = reader.readLine() ?: break
                lastLine = line
            }
            return lastLine ?: ""
        }
    }

    fun mapToSeverityDesc(finalSeverity: Float): String = when (finalSeverity) {
        in 1.0..1.5  -> "无症状"
        in 1.5..2.5  -> "轻度"
        in 2.5..3.5  -> "轻度"
        in 3.5..4.5  -> "中度"
        in 4.5..5.5  -> "中度"
        in 5.5..6.5  -> "中度"
        in 6.5..7.5  -> "重度"
        in 7.5..8.5  -> "重度"
        in 8.5..9.5  -> "极重度"
        else         -> "死亡"
    }

    private fun calculateFinalSeverity(
        modelOutput: FloatArray,
        faceVal: Float = 5.0f,
        ultrasoundVal: String? = null
    ): Float {
        // 如果超声结果有值，优先判断
        if (!ultrasoundVal.isNullOrBlank()) {
            val usValues = ultrasoundVal.split("、").mapNotNull { it.trim().toIntOrNull() }.toSet()

            return when {
                // 气胸(1) + 骨折(2) -> 中度
                usValues.contains(1) || usValues.contains(2) -> 4f
                // 腹腔出血(3) 或 颅脑出血(4) -> 重度
                usValues.contains(3) || usValues.contains(4) -> 7f
                // 单独情况
                usValues.contains(1) -> 2f   // 气胸
                usValues.contains(2) -> 2f   // 骨折
                usValues.contains(3) -> 7f   // 腹腔出血
                usValues.contains(4) -> 7f   // 颅脑出血
                else -> 5f // 默认值
            }
        }

        // ---- 原有模型逻辑 ----
        val predClass = modelOutput.indices.maxByOrNull { modelOutput[it] } ?: 0
        val xValue = when (predClass) {
            0 -> 1f
            1, 2 -> 2f
            3, 4, 5 -> 4f
            6, 7 -> 7f
            8 -> 9f
            9 -> 10f
            else -> 1f
        }

        val alpha = 0.5f
        val beta = 0.5f

        return (alpha * xValue + beta * faceVal).coerceIn(1f, 10f)
    }

    // 保存到 /Download/ALResults，中文不会乱码
    private fun saveResults(patientId: String, severityDescription: String) {
        try {
            val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
            val resultDir = File(downloadsDir, "ALResults").apply { if (!exists()) mkdirs() }

            // 允许中文，替换非法文件名字符
            val safePatientId = patientId.replace(Regex("[\\\\/:*?\"<>|]"), "_")
            val resultFile = File(resultDir, "severity_result_${safePatientId}.json")

            val resultJson = JSONObject().apply {
                put(patientId, severityDescription)
            }

            FileOutputStream(resultFile).use {
                it.write(resultJson.toString(4).toByteArray(StandardCharsets.UTF_8))
            }

            Log.i("SaveResults", "保存成功: ${resultFile.absolutePath}")
        } catch (e: Exception) {
            Log.e("SaveResults", "保存失败: ${e.message}")
        }
    }

    private fun parseCsvLine(line: String): List<String> {
        val result = mutableListOf<String>()
        var inQuotes = false
        val currentField = StringBuilder()
        for (c in line) {
            when {
                c == '"' -> inQuotes = !inQuotes
                c == ',' && !inQuotes -> {
                    result.add(currentField.toString())
                    currentField.clear()
                }
                else -> currentField.append(c)
            }
        }
        result.add(currentField.toString())
        return result
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(text = "$name 正在运行...", modifier = modifier)
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    ExptTheme {
        Greeting("伤害评估系统")
    }
}
